import type { BookingContext } from '@shared/types/automation'
import type {
  JobStatus,
  ScriptRunRequest,
  ScriptRunResponse,
  ScriptStatusRequest,
  ScriptStatusResponse,
  ScriptStopRequest,
  ScriptStopResponse,
} from '@shared/types/ipc'
// 脚本执行 IPC 处理器
import { ipcMain } from 'electron'
import { v4 as uuidv4 } from 'uuid'
import { getBookingEngine } from '../automation/booking-engine'
import { cleanupBrowser } from '../automation/index'
import { getDatabase } from '../db/index'
import { getLogger } from '../logger/index'

// 任务状态管理
const runningJobs = new Map<string, {
  status: JobStatus['status']
  progress: number
  current_step: string
  start_time: number
  controller?: AbortController
}>()

export function setupScriptHandlers(): void {
  const logger = getLogger()

  // 脚本：运行
  ipcMain.handle('script:run', async (_event, request: ScriptRunRequest): Promise<ScriptRunResponse> => {
    try {
      // 校验请求
      if (!request.user_info) {
        return { success: false, job_id: '', message: '用户信息不能为空', error: 'INVALID_PARAMS' }
      }

      const jobId = uuidv4()
      const prisma = getDatabase()
      const now = Math.floor(Date.now() / 1000)

      // 使用 Prisma Client 记录任务
      await prisma.job.create({
        data: {
          id: jobId,
          type: 'script',
          mode: request.mode,
          status: 'pending',
          user_info: JSON.stringify(request.user_info),
          options: JSON.stringify(request.options || {}),
          created_at: now,
          updated_at: now,
        },
      })

      // 初始化内存状态
      runningJobs.set(jobId, {
        status: 'pending',
        progress: 0,
        current_step: '准备启动',
        start_time: Date.now(),
        controller: new AbortController(),
      })

      // 异步执行脚本
      void executeScript(jobId, request).catch((error) => {
        logger.error(`任务 ${jobId} 执行失败:`, error)
        void updateJobStatus(jobId, 'failed', 100, '执行失败', (error as any)?.message)
      })

      logger.info(`✅ 脚本任务已创建 ${jobId}`, { mode: request.mode })
      return { success: true, job_id: jobId, message: '任务已启动' }
    }
    catch (error) {
      logger.error('启动脚本任务失败:', error)
      return { success: false, job_id: '', message: '启动任务失败', error: (error as any)?.message }
    }
  })

  // 脚本：停止
  ipcMain.handle('script:stop', async (_event, request: ScriptStopRequest): Promise<ScriptStopResponse> => {
    try {
      const job = runningJobs.get(request.job_id)
      if (!job) {
        return { success: false, message: '任务不存在或已完成' }
      }
      if (job.controller)
        job.controller.abort()
      await updateJobStatus(request.job_id, 'cancelled', job.progress, '已取消')
      runningJobs.delete(request.job_id)
      getLogger().info(`🛑 任务已停止 ${request.job_id}`)
      return { success: true, message: '任务已停止' }
    }
    catch (error) {
      getLogger().error('停止任务失败:', error)
      return { success: false, message: '停止任务失败' }
    }
  })

  // 脚本：状态查询
  ipcMain.handle('script:status', async (_event, request: ScriptStatusRequest): Promise<ScriptStatusResponse> => {
    try {
      const prisma = getDatabase()
      const jobs = await prisma.job.findMany({
        where: request.job_id ? { id: request.job_id } : undefined,
        orderBy: { created_at: 'desc' },
        take: 50,
        select: {
          id: true,
          type: true,
          status: true,
          progress: true,
          current_step: true,
          started_at: true,
          completed_at: true,
          result: true,
          error_message: true,
        },
      })
      // 与内存状态合并：保证已结束但内存仍残留或反之的场景可以自我修正
      const now = Math.floor(Date.now() / 1000)
      const fixed = jobs.map((job) => {
        const r = runningJobs.get(job.id)
        // 若 DB 非 running 但内存残留，清理内存
        if (r && job.status !== 'running') {
          runningJobs.delete(job.id)
        }
        // 若 DB 是 running 但 started_at 距今超过 8 小时且无内存项，则判定为僵尸，修正为 cancelled
        if (!r && job.status === 'running' && job.started_at && (now - job.started_at) > 8 * 3600) {
          return { ...job, status: 'cancelled' as const, completed_at: job.completed_at || now }
        }
        return job
      })
      const jobStatuses: JobStatus[] = fixed.map((job) => {
        const runningJob = runningJobs.get(job.id)
        const castStatus = (value: any): JobStatus['status'] => {
          const allowed = ['pending', 'running', 'success', 'failed', 'cancelled'] as const
          return (allowed as readonly string[]).includes(value) ? (value as JobStatus['status']) : 'pending'
        }
        return {
          job_id: job.id,
          type: (job as any).type,
          status: runningJob?.status || castStatus(job.status),
          progress: runningJob?.progress ?? (job.progress ?? undefined),
          current_step: runningJob?.current_step ?? (job.current_step ?? undefined),
          start_time: job.started_at ?? undefined,
          end_time: job.completed_at ?? undefined,
          result: job.result ? JSON.parse(job.result as any) : undefined,
          error: (job.error_message ?? undefined) as any,
        }
      })
      return { success: true, jobs: jobStatuses }
    }
    catch (error) {
      getLogger().error('查询任务状态失败:', error)
      return { success: false, jobs: [] }
    }
  })

  // 脚本：清空历史
  ipcMain.handle('script:clear', async (_event, request: { keep_running?: boolean, older_than?: number }) => {
    try {
      const prisma = getDatabase()
      const keepRunning = request?.keep_running !== false
      const olderThan = request?.older_than

      // 基础条件：仅删除非运行中任务（可选）
      const whereBase: any = keepRunning
        ? { NOT: { status: 'running' } }
        : {}

      // 时间条件：仅删除早于给定秒级时间戳的记录（可选）
      const whereFinal: any = olderThan
        ? { AND: [whereBase, { created_at: { lt: olderThan } }] }
        : whereBase

      // 执行删除
      const res = await prisma.job.deleteMany({ where: whereFinal })
      getLogger().info('🧹 脚本历史清理完成', { deleted: res.count, keepRunning, olderThan })
      return { success: true, deleted_count: res.count }
    }
    catch (error) {
      getLogger().error('清空脚本历史失败:', error)
      return { success: false, deleted_count: 0, error: (error as any)?.message || String(error) }
    }
  })
}

// 执行脚本任务（完整预约流程）
async function executeScript(jobId: string, request: ScriptRunRequest): Promise<void> {
  const logger = getLogger()
  const bookingEngine = getBookingEngine()

  try {
    await updateJobStatus(jobId, 'running', 5, '初始化预约引擎')

    // 构建预约上下文
    const context: BookingContext = {
      user_info: {
        passport_number: request.user_info.passport_number,
        license_number: request.user_info.license_number,
        license_owner_name: request.user_info.license_owner_name,
        email: request.user_info.email,
        phone_number: request.user_info.phone_number,
        issuing_country: request.user_info.issuing_country || 'CN',
        issuing_authority: request.user_info.issuing_authority || 'GD',
        service_type: request.user_info.service_type || 'DI',
      },
      preferred_dates: request.preferred_dates,
      preferred_times: request.preferred_times,
      options: {
        headless: request.options?.headless ?? true,
        timeout: request.options?.timeout ?? 30000,
        save_html: true,
      },
    }

    // 设置进度回调
    const originalGetProgress = bookingEngine.getProgress.bind(bookingEngine)
    const originalGetCurrentStep = bookingEngine.getCurrentStep.bind(bookingEngine)

    // 启动预约流程监控
    const progressInterval = setInterval(async () => {
      const progress = originalGetProgress()
      const currentStep = originalGetCurrentStep()
      if (progress > 0) {
        await updateJobStatus(jobId, 'running', progress, currentStep)
      }
    }, 1000)

    try {
      // 执行完整预约流程
      const result = await bookingEngine.execute(context)

      clearInterval(progressInterval)

      if (result.success) {
        const finalResult = {
          reference_number: result.reference_number,
          selected_date: context.selected_date,
          selected_timeslot: context.selected_timeslot?.display_time || context.selected_timeslot?.start_time,
        }

        await updateJobStatus(jobId, 'success', 100, '预约成功', undefined, finalResult)
        logger.info(`✅ 任务 ${jobId} 预约成功`, finalResult)
      }
      else {
        await updateJobStatus(jobId, 'failed', 100, '预约失败', result.message)
        logger.error(`❌ 任务 ${jobId} 预约失败: ${result.message}`)
      }
    }
    finally {
      clearInterval(progressInterval)
    }
  }
  catch (error) {
    logger.error(`任务 ${jobId} 执行异常:`, error)
    await updateJobStatus(jobId, 'failed', 100, '执行失败', (error as any)?.message)
  }
  finally {
    // 确保资源清理
    try {
      await cleanupBrowser()
    }
    catch (e) {
      logger.warn('清理浏览器资源时出现问题:', e)
    }

    // 从运行任务列表中移除
    runningJobs.delete(jobId)
  }
}

// 更新任务状态
async function updateJobStatus(
  jobId: string,
  status: JobStatus['status'],
  progress: number,
  currentStep: string,
  error?: string,
  result?: any,
): Promise<void> {
  const prisma = getDatabase()
  const now = Math.floor(Date.now() / 1000)
  // 内存状态
  const job = runningJobs.get(jobId)
  if (job) {
    job.status = status
    job.progress = progress
    job.current_step = currentStep
  }
  // 数据库字段
  await prisma.job.update({
    where: { id: jobId },
    data: {
      status,
      progress,
      current_step: currentStep,
      updated_at: now,
      ...(error ? { error_message: error } : {}),
      ...(result ? { result: JSON.stringify(result) } : {}),
    },
  })
  // started_at（仅第一次 running 写入）
  if (status === 'running') {
    const row = await prisma.job.findUnique({ where: { id: jobId }, select: { started_at: true } })
    if (!row?.started_at) {
      await prisma.job.update({ where: { id: jobId }, data: { started_at: now } })
    }
  }
  // completed_at（终态写入）
  if (['success', 'failed', 'cancelled'].includes(status)) {
    await prisma.job.update({ where: { id: jobId }, data: { completed_at: now } })
  }
}
